package naga.x.platform2.utils;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.ByteArrayOutputStream;
import java.io.Closeable;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.Flushable;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.URL;
import java.nio.charset.Charset;

public class IOUtils {
	
	public static final String DEFAULT_ENCODE = System.getProperty("sun.jnu.encoding");
	public static final String UTF8 = "utf-8";
	public static final String GBK = "gbk";

	public static interface LineReaderListener {
		public boolean readLine(String line);
	}
	
	private IOUtils() {}
	
	public static String read(File file) {
		return read(file, DEFAULT_ENCODE);
	}
	
	public static String read(File file, String charset) {
		try {
			return read(new FileInputStream(file), charset);
		} catch (FileNotFoundException e) {
		}
		return null;
	}
	
	public static void read(File file, LineReaderListener listener) {
		read(file, DEFAULT_ENCODE, listener);
	}
	
	public static void read(File file, String charset, LineReaderListener listener) {
		try {
			readLineByLine(new FileInputStream(file), charset, listener);
		} catch (FileNotFoundException e) {
		}
	}
	
	public static String read(InputStream in) {
		return read(in, DEFAULT_ENCODE);
	}
	
	public static String read(InputStream in, String charset) {
		final StringBuilder buf = new StringBuilder();
		readLineByLine(in, charset, new LineReaderListener() {
			@Override
			public boolean readLine(String line) {
				buf.append(line).append(System.lineSeparator());
				return true;
			}
		});
		return buf.toString();
	}
	
	public static void readLineByLine(InputStream in, LineReaderListener listener) {
		readLineByLine(in, DEFAULT_ENCODE, listener);
	}
	
	public static void readLineByLine(InputStream in, String charset, LineReaderListener listener) {
		if (listener == null) {
			throw new NullPointerException("LineReaderListener can't be null.");
		}
		if (charset == null) {
			charset = DEFAULT_ENCODE;
		}
		BufferedReader reader = null;
		try {
			reader = new BufferedReader(new InputStreamReader(in, charset));
			String line;
			while ((line = reader.readLine()) != null) {
				if (!listener.readLine(line)) {
					break;
				}
			}
		} catch (IOException e) {
		} finally {
			closeQuietly(reader);
		}
	}
	
	public static byte[] readBytes(InputStream in) {
		try {
			ByteArrayOutputStream buf = new ByteArrayOutputStream(1024);
			byte[] b = new byte[1024];
			int len;
			while ((len = in.read(b)) > 0) {
				buf.write(b, 0, len);
			}
			return buf.toByteArray();
		} catch (IOException e) {
		} finally {
			closeQuietly(in);
		}
		return null;
	}
	
	public static void closeQuietly(Closeable stream) {
		if (stream != null) {
			try {
				stream.close();
			} catch (IOException e) {
			}
		}
	}
	
	public static void flushQuietly(Flushable f) {
		if (f != null) {
			try {
				f.flush();
			} catch (IOException e) {}
		}
	}
	
	public static byte[] getStringBytes(String str) {
		return getStringBytes(str, DEFAULT_ENCODE);
	}
	
	public static byte[] getStringBytes(String str, String charset) {
		try {
			return getStringBytes(str, Charset.forName(charset));
		} catch (Exception e) {}
		return null;
	}
	
	public static byte[] getStringBytes(String str, Charset charset) {
		try {
			return str.getBytes(charset);
		} catch (Exception e) {
		}
		return null;
	}
	
	public static URL getResource(String name) {
		return Thread.currentThread().getContextClassLoader().getResource(name);
	}
	
	public static InputStream getResourceAsStream(String name) {
		return Thread.currentThread().getContextClassLoader().getResourceAsStream(name);
	}
	
	public static String getResourceAsString(String resource) {
		InputStream in = null;
		try {
			in = getResourceAsStream(resource);
			ByteArrayOutputStream out = new ByteArrayOutputStream(1024);
			byte[] buf = new byte[128];
			int len;
			while ((len = in.read(buf)) != -1) {
				out.write(buf, 0, len);
			}
			return new String(out.toByteArray(), UTF8);
		} catch (Exception e) {
		} finally {
			closeQuietly(in);
		}
		return null;
	}
	
	public static void write(File file, String text, String charset) {
		BufferedWriter writer = null;
		try {
			writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(createNewFile(file)), charset));
			writer.write(text);
			flushQuietly(writer);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			closeQuietly(writer);
		}
	}
	
	public static void write(File file, byte[] bytes) {
		FileOutputStream out = null;
		try {
			out = new FileOutputStream(createNewFile(file));
			out.write(bytes);
			out.flush();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			closeQuietly(out);
		}
	}
	
	public static File createNewFile(File file) {
		if (file.exists()) {
			return file;
		}
		File parent = file.getParentFile();
		if (parent != null && !parent.exists()) {
			parent.mkdirs();
		}
		try {
			file.createNewFile();
		} catch (IOException e) {
		}
		return file;
	}
	
}
